<?php

class ContestManager
{
	private $_db;
	
	public function __construct(PDO $db)
	{
		$this->setDb($db);
	}
	
	public function setDb($db)
	{
		$this->_db = $db;
	}
	
	public function add(Contest $contest)
	{
		//Fonction qui va ajouter un contest dans la table contests
		$reqInsert = $this->_db->prepare("INSERT INTO contests SET name= :name, event_id= :event_id, private= :private, creationDate= :creationDate, comment= :comment, creator= :creator, closed= 0");
		$reqInsert->bindValue(":login", $contest->login());
		$reqInsert->bindValue(":name", $contest->name());
		$reqInsert->bindValue(":event_id", $contest->event_id());
		$reqInsert->bindValue(":private", $contest->privateE());
		$reqInsert->bindValue(":creationDate", $contest->creationDate());
		$reqInsert->bindValue(":creator", $contest->creator());
		$reqInsert->bindValue(":comment", $contest->comment());
		$reqInsert->execute();
		$idContest = $this->_db->lastInsertId();
		$contest->hydrate(array(
			'id' => $idContest
		));
	}
	public function delete(Contest $contest)
	{
		//Fonction qui va supprimer un contest dans la table contests
		$reqDelete = $this->_db->prepare("DELETE FROM contests WHERE id= :id");
		$reqDelete->bindValue(":id", $contest->id());
		$reqDelete->execute();
	}
	public function update(Contest $contest)
	{
		//Fonction qui va mettre à jour un contest dans la table contests
		$reqUpdate = $this->_db->prepare("UPDATE contests SET name= :name, event_id= :event_id, private= :private, creationDate= :creationDate, creator= :creator, comment= :comment, closed= :closed WHERE id= :id");
		$reqUpdate->bindValue(":id", $contest->id(), PDO::PARAM_INT);
		$reqUpdate->bindValue(":name", $contest->name(), PDO::PARAM_STR);
		$reqUpdate->bindValue(":event_id", $contest->event_id(), PDO::PARAM_INT);
		$reqUpdate->bindValue(":private", $contest->privateE(), PDO::PARAM_BOOL);
		$reqUpdate->bindValue(":creationDate", $contest->creationDate(), PDO::PARAM_STR);
		$reqUpdate->bindValue(":creator", $contest->creator(), PDO::PARAM_STR);
		$reqUpdate->bindValue(":comment", $contest->comment(), PDO::PARAM_STR);
		$reqUpdate->bindValue(":closed", $contest->closed(), PDO::PARAM_STR);
		$reqUpdate->execute();
	}
	
	public function get($search)
	{
		//Fonction qui va chercher un contest dans la table contests à partir du critère de recherche search
		if(is_int($search))
		{
			$reqSelect = $this->_db->prepare("SELECT * FROM contests WHERE id= :id");
			$reqSelect->bindValue(":id", $search);
			$reqSelect->execute();
			$contest = $reqSelect->fetch(PDO::FETCH_ASSOC);
			if(is_array($contest)) return new Contest($contest);
			return null;
		}
		if(is_string($search))
		{
			$reqSelect = $this->_db->prepare("SELECT * FROM contests WHERE name LIKE %:name%");
			$reqSelect->bindValue(":id", $search);
			$reqSelect->bindValue(":name", $search);
			$reqSelect->execute();
			$contest = $reqSelect->fetch(PDO::FETCH_ASSOC);
			if(is_array($contest)) return new Contest($contest);
			return null;
		}
	}
	public function exist($search)
	{
		//Fonction qui vérifie l'existence d'un contest dans la table contests
		if(is_int($search))
		{
			$reqSelect = $this->_db->prepare("SELECT * FROM contests WHERE id= :id");
			$reqSelect->bindValue(":id", $search);
			$reqSelect->execute();
			return (bool) $reqSelect->fetch();
		}
		if(is_string($search))
		{
			$reqSelect = $this->_db->prepare("SELECT * FROM contests WHERE name= :name");
			$reqSelect->bindValue(":name", $search);
			$reqSelect->execute();
			return (bool) $reqSelect->fetch();
		}
	}
	
	public function getListContests(Sport $sport=null, SportsEvent $sportsEvent=null, Event $event=null, $public=0, User $user=null, $statusPlayer=-2)
	{
		//Fonction qui retourne la liste des contests, par sport ou sportsEvent. Filtre possible sur le caractère public/privé. Filtre possible sur le fait qu'un joueur participe ou non
		//Si sport = null : on restitue tout
		//Si sport != null et sportsEvent = null : on restitue tout pour le sport
		//Si sport != null et sportsEvent != null : on restitue tout pour le sportsEvent
		//Si public = 1 ==> On restitue uniquement les concours publics
		//Si user != null et statusPlayer == -2 ==> On restitue tous les concours
		//Si user != null et statusPlayer == -1 ==> On restitue uniquement les concours où user n'est pas dans la table players
		//Si user != null et statusPlayer == 0 ==> On restitue uniquement les concours où user est dans la table players, quel que soit le statut de participation
		//Si user != null et statusPlayer != 0 ==> On restitue uniquement les concours où user est dans la table players, avec le statusParticipation_id = statusPlayer
		$contests = array();
		$query = "SELECT * FROM contests";
		if($sport != null || $public == 1 || $user != null) 
		{
			$query .= " WHERE ";
			$i = 0;
		}
		if($public == 1)
		{
			$query .= "private=0";
			$i = 1;
		}
		if($sport != null)
		{
			if($i == 1) $query .= " AND ";
			if($sportsEvent == null) $query .= "event_id IN(SELECT id FROM events WHERE sportsEvent_id IN(SELECT id FROM sportsevents WHERE sport_id=".$sport->id()."))";
			else $query .= "event_id IN(SELECT id FROM events WHERE sportsEvent_id=".$sportsEvent->id().")";
			$i = 1;
		}
		if($user != null)
		{
			if($i == 1) $query .= " AND ";
			if($statusPlayer == -2) $query .= "1";
			elseif($statusPlayer == -1) $query .= "id NOT IN(SELECT contest_id FROM players WHERE user_id=".$user->id().")";
			elseif($statusPlayer == 0) $query .= "id IN(SELECT contest_id FROM players WHERE user_id=".$user->id().")";
			else $query .= "id IN(SELECT contest_id FROM players WHERE user_id=".$user->id()." AND statusParticipation_id=".$statusPlayer.")";
		}
		$query.=" ORDER BY event_id";
		$reqList = $this->_db->query($query);
		while($contest = $reqList->fetch(PDO::FETCH_ASSOC))
		{
			$contestL = new Contest($contest);
			$contests[] = $contestL;
		}
		
		$reqList->closeCursor();
		return $contests;
	}
	
	public function getListPlayers(Contest $contest, $status = 0)
	{
		//Fonction qui retourne la liste des users de la table players pour ce contest, avec le statut indiqué par la variable status. Si status = 0 : on restitue tout.
		$users = array();
		if($status==0) $reqList = $this->_db->query("SELECT * FROM users WHERE id IN(SELECT user_id FROM players WHERE contest_id=".$contest->id().")");
		else $reqList = $this->_db->query("SELECT * FROM users WHERE id IN(SELECT user_id FROM players WHERE contest_id=".$contest->id()." AND statusParticipation_id=".$status.")");
		while($user = $reqList->fetch(PDO::FETCH_ASSOC))
		{
			$userL = new User($user);
			$users[] = $userL;
		}
		$reqList->closeCursor();
		return $users;
	}

	public function getPointsPlayers(Sport $sport, Contest $contest, User $user = null)
	{
		//Fonction qui ramène le nombre de points du joueur dans le contest (sur la base de tous ses bets), si User = null alors on ramène un tableau qui récapitule pour chaque player son nombre de points
			//$sport permet de cibler la table bets appropriée
		$betsManager = new BetsManager($this->_db);
		if($user != null)
		{
			$points = 0;
			$bets = $betsManager->get($sport, null, null, $contest, $user);
			foreach($bets as $bet)
			{
				$points += $bet->resultWinningTeam() + $bet->resultPointsDifference() + $bet->resultPointsTotal() + $bet->resultOvertime();
			}
			return $points;
		}
		else
		{
			$points = array();
			$players = $this->getListPlayers($contest, 1);
			foreach($players as $player)
			{
				$pointsPlayer = 0;
				$bets = $betsManager->get($sport, null, null, $contest, $player);
				switch($sport->id())
				{
					case 1:
						$pointsWinningTeam = 0;
						$pointsPointsDifference = 0;
						$pointsPointsTotal = 0;
						$pointsOvertime = 0;
						foreach($bets as $bet)
						{
							$pointsWinningTeam += $bet->resultWinningTeam();
							$pointsPointsDifference += $bet->resultPointsDifference();
							$pointsPointsTotal += $bet->resultPointsTotal();
							$pointsOvertime += $bet->resultOvertime();
							$pointsPlayer += $bet->resultWinningTeam() + $bet->resultPointsDifference() + $bet->resultPointsTotal() + $bet->resultOvertime();
						}
						$points[] = array("rank" => "", "player" => $player, "pointsWinningTeam" => $pointsWinningTeam, "pointsPointsDifference" => $pointsPointsDifference, "pointsPointsTotal" => $pointsPointsTotal, "pointsOvertime" => $pointsOvertime, "pointsPlayer" => $pointsPlayer);
						break;
					default:
						return;
				}
			}
			return $points;
		}
	}
	
	public function getPointsScheduleEvent(Sport $sport, Contest $contest, ScheduleEvent $scheduleEvent, User $user = null, $criteria = null)
	{
		//Fonction qui ramène le nombre de points marqués par le joueur sur un match (scheduleEvent) pour chaque critère (criteria). Si $criteria=null, alors on affiche le total de points marqués sur ce match. Si $criteria = "all", on restitue un tableau avec le détail des points marqués.
			//$sport permet de cibler la table bets appropriée
		
		$eventManager = new EventManager($this->_db);
		$event=$eventManager->get($contest->event_id());
		
		switch($sport->id())
		{
		case 1:
			$betsManager = new BetsManager($this->_db);
			if($user != null) //On veut des résultats pour un joueur en particulier
			{
				$users = array($user);
			}
			else
			{
				$users = $this->getListPlayers($contest, 1);
			}
			$points = array();
			foreach($users as $player)
			{
				$bets = $betsManager->get($sport, null, $scheduleEvent, $contest, $player);
				if($bets!=null)
				{
					if($criteria==null)
					{
						$scheduleEventPoints = $bets->resultWinningTeam() + $bets->resultPointsDifference() + $bets->resultPointsTotal() + $bets->resultOvertime();
						$points[] = array($player, $scheduleEventPoints);
					}
					
					elseif($criteria=="winningTeam")
					{
						$scheduleEventPoints = $bets->resultWinningTeam();
						$points[] = array($player, $scheduleEventPoints);
					}
					
					elseif($criteria=="pointsDifference")
					{
						$scheduleEventPoints = $bets->resultPointsDifference();
						$points[] = array($player, $scheduleEventPoints);
					}
					elseif($criteria=="pointsTotal")
					{
						$scheduleEventPoints = $bets->resultPointsTotal();
						$points[] = array($player, $scheduleEventPoints);
					}
					elseif($criteria=="overTime")
					{
						$scheduleEventPoints = $bets->resultOvertime();
						$points[] = array($player, $scheduleEventPoints);
					}
					elseif($criteria=="all")
					{
						$scheduleEventPoints[] = array("winningTeam" => $bets->resultWinningTeam(), "pointsDifference" => $bets->resultPointsDifference(), "pointsTotal" => $bets->resultPointsTotal(), "overTime" => $bets->resultOvertime(), "total" => $bets->resultWinningTeam()+$bets->resultPointsDifference()+$bets->resultPointsTotal()+$bets->resultOvertime());
						$points[] = array($player, $scheduleEventPoints);
					}
				}
				else $points[] = array($player, 0);
			}
			return $points;
			break;
		}
	}
	
	public function calculateRanking(Sport $sport, Contest $contest)
	{
		$rankingContest = $this->getPointsPlayers($sport, $contest);
		foreach($rankingContest as $key => $row)
		{
			$pointsPlayer[$key] = $row['pointsPlayer'];
		}
		array_multisort($pointsPlayer, SORT_DESC, $rankingContest);
		$i = 0;
		foreach($rankingContest as $key => $row)
		{
			$i++;
			if(isset($previousPlayer) && $row['pointsPlayer']==$previousPlayer) $rank=$rank;
			else $rank=$i;
			$row['rank']=$rank;
			$previousPlayer=$row['pointsPlayer'];
			$rankingContest[$i-1] = $row;
		}
		return $rankingContest;
	}
	
	public function sortRanking(Sport $sport, $ranking, $sortCriteria = "pointsPlayer", $sortOrder = SORT_DESC)
	{
		switch($sport->id())
		{
			case 1:
				//Tri du tableau de résultat pour faire le classement
				foreach ($ranking as $key => $row)
				{
					$rank[$key] = $row['rank'];
					$player[$key] = $row['player'];
					$pointsWinningTeam[$key] = $row['pointsWinningTeam'];
					$pointsPointsDifference[$key] = $row['pointsPointsDifference'];
					$pointsPointsTotal[$key] = $row['pointsPointsTotal'];
					$pointsOvertime[$key] = $row['pointsOvertime'];
					$pointsPlayer[$key] = $row['pointsPlayer'];
				}
				array_multisort($$sortCriteria, $sortOrder, $player, SORT_ASC, $ranking);
				break;
			default:
				return;
		}
		return $ranking;
	}
	
	public function getListMessages($contest, $post = null)
	{
		//Fonction qui retourne la liste des messages de la table messages pour ce contest.
		$messages = array();
		if($post == null) $reqList = $this->_db->query("SELECT * FROM messages WHERE contest_id = ".$contest->id()." ORDER BY messageDate DESC");
		if($post == 0) $reqList = $this->_db->query("SELECT * FROM messages WHERE contest_id = ".$contest->id()." AND responseMessage_id=0 ORDER BY messageDate DESC");
		else $reqList = $this->_db->query("SELECT * FROM messages WHERE contest_id = ".$contest->id()." AND responseMessage_id=".$post." ORDER BY messageDate ASC");
		while($message = $reqList->fetch(PDO::FETCH_ASSOC))
		{
			$messageL = new Message($message);
			$messages[] = $messageL;
		}
		$reqList->closeCursor();
		return $messages;
	}
	
	public function getCreator($contest)
	{
		//Fonction qui retourne le créateur du concours
		$reqCreator = $this->_db->query("SELECT creator FROM contests WHERE id=".$contest->id()."");
		$userManager = new UserManager($this->_db);
		$creatorId = $reqCreator->fetch(PDO::FETCH_ASSOC);
		$creator = $userManager->get((int) $creatorId['creator']);
		return $creator;
	}
	
	public function getStatus($contest)
	{
		//Fonction qui retourne le statut du concours (à venir, ouvert, fermé)
		$reqStatus = $this->_db->query("SELECT creationDate, closed FROM contests WHERE id='".$contest->id()."'");
		$resultReqStatus = $reqStatus->fetch(PDO::FETCH_ASSOC);
		if($resultReqStatus['closed']==1) return "Clos";
		elseif($resultReqStatus['closed']==0 && time()-strtotime($resultReqStatus['creationDate'])<0) return "A venir";
		else return "En cours";
	}
	
	public function getScheduleEvents(Sport $sport, Contest $contest, $round = null, $date = null)
	{
		//Fonction qui retourne la liste des matchs d'un concours selon certains critères : round (ex : 1er tour ou 13e journée) ou date (ex : 04/05/15)
		$eventManager = new EventManager($this->_db);
		$event = $eventManager->get($contest->event_id());
		switch($sport->id())
		{
			case 1:
				if($date!=null) //Le filtre date est prioritaire
				{
					$reqSelect = $this->_db->query("SELECT * FROM scheduleevent_basket WHERE event_id='".$event->id()."' AND DATE(dateE)='".$date."' ORDER BY dateE");
				}
				else
				{			
					$currentRound = $this->getCurrentRound($sport, $contest);
					if($round == "current")
					{
						if($currentRound == null) return null;
						$reqSelect = $this->_db->query("SELECT * FROM scheduleevent_basket WHERE event_id='".$event->id()."' AND round='".$currentRound."' ORDER BY dateE");
					}
					elseif($round == "next")
					{
						if($currentRound == null) $current = 0;
						else $current = $currentRound;
						$reqSearchNextRound = $this->_db->query("SELECT round FROM scheduleevent_basket WHERE event_id='".$event->id()."' AND dateE > NOW() ORDER BY dateE");
						while($resultReqSearchNextRound = $reqSearchNextRound->fetch(PDO::FETCH_ASSOC))
						{
							if($resultReqSearchNextRound['round']!=$current)
							{
								$nextRound = $resultReqSearchNextRound['round'];
								break;
							}
						}
						if($resultReqSearchNextRound == null) return null;
						$reqSelect = $this->_db->query("SELECT * FROM scheduleevent_basket WHERE event_id='".$event->id()."' AND round='".$nextRound."' ORDER BY dateE");
					}
					elseif($round == "previous")
					{
						if($currentRound == null) $current = "0";
						else $current = $currentRound;
						$reqSearchPreviousRound = $this->_db->query("SELECT round FROM scheduleevent_basket WHERE event_id='".$event->id()."' AND dateE <= NOW() ORDER BY dateE DESC");
						while($resultReqSearchPreviousRound = $reqSearchPreviousRound->fetch(PDO::FETCH_ASSOC))
						{
							if($resultReqSearchPreviousRound['round'] != $current)
							{
								$previousRound = $resultReqSearchPreviousRound['round'];
								break;
							}
						}
						if($resultReqSearchPreviousRound == null) return null;
						$reqSelect = $this->_db->query("SELECT * FROM scheduleevent_basket WHERE event_id='".$event->id()."' AND round='".$previousRound."' ORDER BY dateE");
					}
					else
					{
						$reqSelect = $this->_db->query("SELECT * FROM scheduleevent_basket WHERE event_id='".$event->id()."' AND round='".$round."' ORDER BY dateE");
					}
				}
				$listScheduleEventsPast = array();
				$listScheduleEventsToCome = array();
				while($scheduleEvent = $reqSelect->fetch(PDO::FETCH_ASSOC))
				{
					$scheduleEventL = new ScheduleEventBasket($scheduleEvent);
					if($scheduleEventL->dateE()<=date("Y-m-d H:m:i")) $listScheduleEventsPast[] = $scheduleEventL;
					else $listScheduleEventsToCome[] = $scheduleEventL;
				}
				$reqSelect->closeCursor();
				$listScheduleEvents = array($listScheduleEventsPast, $listScheduleEventsToCome);
				return $listScheduleEvents;
			default:
				return;
		}
	}

	public function getCurrentRound(Sport $sport, Contest $contest)
	{
		//Fonction qui retourne le round en cours d'un concours
		$eventManager = new EventManager($this->_db);
		$event=$eventManager->get($contest->event_id());
		
		switch($sport->id())
		{
			case 1: //basket
		$reqRoundA = $this->_db->query("SELECT round FROM scheduleEvent_basket WHERE dateE>NOW() ORDER BY dateE LIMIT 0,1");
		$resultRoundA = $reqRoundA->fetch(PDO::FETCH_ASSOC);
		
		if($resultRoundA==null) $currentRound=null; //dernier round terminé
		else {
			$reqRoundB = $this->_db->query("SELECT round FROM scheduleEvent_basket WHERE dateE<NOW() ORDER BY dateE DESC LIMIT 0,1");
			$resultRoundB = $reqRoundB->fetch(PDO::FETCH_ASSOC);
			if($resultRoundB==null) $currentRound=null; //premier round pas commencé
			else{
				if($resultRoundA['round']==$resultRoundB['round'])
				{
					$currentRound=$resultRoundA['round'];
				}
				else $currentRound=null; //entre deux rounds
				} 
			}
		return $currentRound;
		
		}
	
	}
	
}

?>